用途:画像の傾きを補正する。OCR読み取りの前処理などに使用。
用法:他のノートと異なり、画像単位で傾きを検知する。
注意:手差しトレイでスキャンした後の傾きを補正する用です。お洒落な画像が傾いちゃったとかは対応できないと思います。
import cv2
import os
import re
import numpy as np
import glob
IMAGE_DIR = 'images/AdjustHolizonLine/'
IMAGE_TYPE = 'JPEG'
IMAGE_EXTENTION = 'jpg'
# 前半の個別で見たい画像ファイル名
IMAGE_NAME = 'test002.jpg'
COLOR_INVERSION=240
LINE_COLOR = (0, 0, 0)
FILL_COLOR = (255, 255, 255)
FILL_THICKNESS = 4
VERTICAL_HORIZONAL_DIFF = 0.00001
KSIZE = 3
このjupyter notebookで使用する諸々の関数です。なにも気にしないで実行してください。
from IPython.display import display, Image
def display_cv_image(image, format='.' + IMAGE_EXTENTION):
decoded_bytes = cv2.imencode(format, image)[1].tobytes()
display(Image(data=decoded_bytes))
img = cv2.imread(IMAGE_DIR + IMAGE_NAME)
display_cv_image(img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, binarized = cv2.threshold(gray, COLOR_INVERSION, 255, cv2.THRESH_BINARY_INV)
display_cv_image(binarized)
kernel = np.ones((3,1),np.uint8)
dilation = cv2.dilate(binarized,kernel,iterations = 1)
display_cv_image(dilation)
image, contours, hierarchy = cv2.findContours(dilation,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img_rect = cv2.drawContours(img, contours, -1, (0,255,0), 3)
display_cv_image(img_rect)
# 矩形検出された数(デフォルトで0を指定)
detect_count = 0
img_rect = cv2.imread(IMAGE_DIR + IMAGE_NAME)
for contour in contours:
# 輪郭の領域を計算
area = cv2.contourArea(contour)
# ノイズ(小さすぎる領域)と全体の輪郭(大きすぎる領域)を除外
if area < 1e4 or 1e5 < area:
continue
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(img_rect, (x, y), (x + w, y + h), (255, 255, 255), 3)
detect_count = detect_count + 1
display_cv_image(img_rect)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img_rect,kernel,iterations = 1)
tmp = 255 - img_rect
closing = cv2.morphologyEx(tmp, cv2.MORPH_CLOSE, kernel)
display_cv_image(closing)
dilation = cv2.dilate(tmp,kernel,iterations = 1)
display_cv_image(dilation)
result = 255 - dilation
display_cv_image(result)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=KSIZE)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=KSIZE)
display_cv_image(laplacian)
display_cv_image(sobelx)
display_cv_image(sobely)
display_cv_image(sobely*255)
print('before')
display_cv_image(binarized)
for i in range(5):
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=2*i+1)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=2*i+1)
print(2*i+1)
display_cv_image(sobely)
import cv2
import numpy as np
## (1) read
img = cv2.imread(IMAGE_DIR + IMAGE_NAME)
display_cv_image(img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
## (2) threshold
th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)
## (3) minAreaRect on the nozeros
pts = cv2.findNonZero(threshed)
ret = cv2.minAreaRect(pts)
(cx,cy), (w,h), ang = ret
if w>h:
w,h = h,w
ang += 90
## (4) Find rotated matrix, do rotation
M = cv2.getRotationMatrix2D((cx,cy), ang, 1.0)
rotated = cv2.warpAffine(threshed, M, (img.shape[1], img.shape[0]))
## (5) find and draw the upper and lower boundary of each lines
hist = cv2.reduce(rotated,1, cv2.REDUCE_AVG).reshape(-1)
th = 2
H,W = img.shape[:2]
uppers = [y for y in range(H-1) if hist[y]<=th and hist[y+1]>th]
lowers = [y for y in range(H-1) if hist[y]>th and hist[y+1]<=th]
rotated = cv2.cvtColor(rotated, cv2.COLOR_GRAY2BGR)
for y in uppers:
cv2.line(rotated, (0,y), (W, y), (255,0,0), 1)
for y in lowers:
cv2.line(rotated, (0,y), (W, y), (0,255,0), 1)
# cv2.imwrite("result.png", rotated)
display_cv_image(rotated)
display_cv_image(rotated)
remove_noise = cv2.fastNlMeansDenoising(gray, 7, 7, 21)
display_cv_image(gray)
display_cv_image(remove_noise)
sobely = cv2.Sobel(gray,cv2.CV_64F,0,1,ksize=KSIZE)
display_cv_image(sobely)